#include "service.h"

#ifdef _SERVER_
#include "./server/gateway.h"
#else
#include "./client/gateway.h"
#endif

CreatorMap	ServiceFactory::m_creatorMap;

Service::Service() 
: m_gateway(NULL)
, m_serviceManager(NULL)
, m_packet(NULL)
, m_bDone(false)
, m_handle(0)
, m_ref(0)
{
}

Service::~Service() 
{
	SAFE_DELETE(m_packet);
}

void Service::Initialize(ServiceManager* manager, const vector<string>& params, NetPacket* packet)
{
	m_serviceManager = manager;
	m_gateway  		 = manager->GetGateway();
	m_params		 = params;
	m_bDone			 = false;	
	
	m_packet = SAFE_NEW NetPacket();
	if(packet != NULL)
		*m_packet = *packet;
}

string Service::GetStringParam(uint16 paramIndex)
{
	if(paramIndex < m_params.size())
		return m_params[paramIndex];
	else
		return "";
}

int Service::GetIntParam(uint16 paramIndex)
{
	if(paramIndex < m_params.size())
		return ParseInt(m_params[paramIndex]);
	else
		return 0;
}

ServiceManager::ServiceManager(Gateway* gateway) 
: m_gateway(gateway)
, m_counter(0)
{
	m_serviceFactory = SAFE_NEW ServiceFactory();
}

ServiceManager::~ServiceManager() 
{
	SAFE_DELETE(m_serviceFactory);
}

void ServiceManager::Update()
{	
	while(m_appendQueue.size() > 0)
	{
		Service* pService = m_appendQueue.front();

		m_workList.push_back(pService);

		m_appendQueue.pop();
	}

	while(m_removeQueue.size() > 0)
	{
		Service* pService = m_removeQueue.front();

		ServiceMap::iterator iter = m_srvMap.find(pService->m_handle);

		if(iter != m_srvMap.end())
		{
			m_srvMap.erase(iter);
		}

		SAFE_DELETE(pService);

		m_removeQueue.pop();
	}

	for(ServiceList::iterator i = m_workList.begin(); i != m_workList.end();)
	{
		Service* pService = (*i);

		if(!pService->IsDone())
		{
			pService->Update();
			++i;
		}
		else
		{
			if(pService->m_ref > 0)
			{
				++i;
			}
			else
			{
				m_removeQueue.push(pService);	

				i = m_workList.erase(i);
			}
		}
	}
}

ServiceHandle ServiceManager::CallService(const string& name, const vector<string>& params, NetPacket* packet)
{
	Service* service = m_serviceFactory->Create(name);

	if(service != NULL)
	{
		service->Initialize(this, params, packet);
		service->m_handle = ++m_counter;

		m_appendQueue.push(service);

		m_srvMap[service->m_handle] = service;

		LOGOUT("ServiceManager: %s Call %s\n", m_gateway->GetUid().c_str(), name.c_str());

		return service->m_handle;
	}
	else
	{
		return -1;
	}
}

Service* ServiceManager::FindService(ServiceHandle handle)
{
	ServiceMap::iterator i = m_srvMap.find(handle);

	if(i != m_srvMap.end())
	{
		return (*i).second;
	}
	else
	{
		return NULL;
	}
}

Service* ServiceManager::AddRef(ServiceHandle handle)
{
	Service* pService = FindService(handle);

	if(pService != NULL)
	{
		++pService->m_ref;
	}

	return pService;
}

void ServiceManager::ReleaseRef(ServiceHandle handle)
{
	Service* pService = FindService(handle);

	if(pService != NULL && pService->m_ref > 0)
	{
		--pService->m_ref;
	}
	else
	{
		ASSERT(0);
	}
}

Service* ServiceFactory::Create(const string& name)
{
	CreatorMap::iterator iter = m_creatorMap.find(name);

	if(iter == m_creatorMap.end())
	{
		ASSERT(0);
		return NULL;
	}
	else
	{
		return  m_creatorMap[name]();
	}
}